package com.linjiahao.oss.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.linjiahao.oss.vo.HmacVO;
import com.linjiahao.oss.vo.ResumeEsHmacVO;
import com.linjiahao.servicebase.commo.online_education_Exception;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @description: 贵州国密工具类
 * @author: HuangWeijie
 * @time: 2021/9/23
 */
@Component
public class StateSecretUtil {

    private static final transient Logger LOGGER = LoggerFactory.getLogger(com.linjiahao.oss.util.StateSecretUtil.class);
    

    //启用国密标志,1:启用,0:禁用
    private static String ENABLE_STATE_SECRET="1";

    public static String ORG_ID =  "orgId";

    @Autowired
    public  RedisTemplate<String, String> redisUtil;


    /**
     * @description: 字符串加密
     */
    public static String stateSecretEncrypt(Object object) throws Exception {
        if (StringUtils.isBlank((String)object)){
            return null;
        }
        String encrypStr =(String)object;
        return encrypStr;
    }

    /**
     * @description: 字符串解密
     */
    public static String stateSecretDecrypt(Object object) throws Exception {
        if (StringUtils.isBlank((String)object)){
            return null;
        }
        String decrypStr = (String)object;
        return decrypStr;
    }

    /**
     * @description: 多行加密
     */
    public  List<String> stateSecretEncrypt(List<Object> lists) throws Exception {
        JSONObject jsonObject = new JSONObject();
        JSONObject nullJson = new JSONObject();
        for (int i = 0; i < lists.size(); i++) {
            if ( StringUtils.isEmpty((String)lists.get(i))){
                nullJson.put("field"+i, "");
            }else {
                jsonObject.put("field"+i, (String)lists.get(i));
            }
        }
        JSONObject jsonResult =jsonObject;
        jsonResult.putAll(nullJson);
        List<String> list = new ArrayList<>();
        for (int j = 0; j < jsonResult.entrySet().size(); j++) {
            list.add((String) jsonResult.get("field" + j));
        }
        return list;
    }

    /**
     * @description: 多行解密
     */
    public  List<String> stateSecretDecrypt(List<Object> lists) throws Exception {
        JSONObject jsonObject = new JSONObject();
        JSONObject nullJson = new JSONObject();
        for (int i = 0; i < lists.size(); i++) {
            if (StringUtils.isEmpty((String)lists.get(i))){
                nullJson.put("field"+i, "");
            }else {
                jsonObject.put("field"+i, (String)lists.get(i));
            }
        }
        JSONObject jsonResult = jsonObject;
        jsonResult.putAll(nullJson);
        List<String> list = new ArrayList<>();
        for (int i1 = 0; i1 < jsonResult.entrySet().size(); i1++) {
            list.add((String) jsonResult.get("field" + i1));
        }
        return list;
    }

    //验签和签名时，如果传入的值为空，则签名此字符串
    private static String signNullValue = "空值";

    /**
     * @description: HMAC验证码验签
     */
    public void stateSecretHmac(String agentCode, String tableName, String field, Map<String, String> fieldValueMap) throws Exception {
        for (Map.Entry<String, String> entry : fieldValueMap.entrySet()) {
            if (StringUtils.isBlank(entry.getKey())){
                System.out.println("-1"+"传入的表字段主键值为空");
            }
            //判断es中是否存在该键值
            String key = agentCode+"*"+tableName+"*"+field.toLowerCase()+"*"+entry.getKey();
            if (StringUtils.isEmpty(entry.getValue())){
                checkStateSecretHmac(key, signNullValue);
            }else {
                checkStateSecretHmac(key, entry.getValue());
            }
        }
    }

    /**
     * @description: HMAC验证码批量验签（查询）
     */
    public  void stateSecretHmac(List<HmacVO> hmacVOList) throws Exception {
        for (HmacVO hmacVO : hmacVOList) {
            if (StringUtils.isBlank(hmacVO.getIdValue())){
                System.out.println("-1"+"传入的表字段主键值为空");
            }
            //判断es中是否存在该键值
            String key = hmacVO.getAgentCode()+"*"+hmacVO.getTableName()+"*"+hmacVO.getField().toLowerCase()+"*"+hmacVO.getIdValue();
            if (StringUtils.isEmpty(hmacVO.getFieldValue())){
                LOGGER.info("HMAC验证码批量验签字段值为空：{}",hmacVO.getField());
                checkStateSecretHmac(key, signNullValue);
            }else {
                checkStateSecretHmac(key, hmacVO.getFieldValue());
            }
        }
    }

    private  void checkStateSecretHmac(String key,String fieldValue){
        /*EsSearchQueryBuilder esSearchQueryBuilder = EsSearchQueryBuilders.builder();
        esSearchQueryBuilder.searchCondition(ElasticDefaultDict.TERM_TYPE,"hmacId",key,ElasticDefaultDict.MUST_BOOL_TYPE);
        List<ResumeEsHmacVO> resumeEsHmacVOS = ElasticUtil.searchByFiled(ORG_ID, esSearchQueryBuilder, ResumeEsHmacVO.class);*/
        ResumeEsHmacVO resumeEsHmacVO = JSON.parseObject(redisUtil.opsForValue().get(key),ResumeEsHmacVO.class);
        String hmac = fieldValue;
        if (resumeEsHmacVO == null){
//            throw new BaseException("-1","字段[" + key + "]验证码值未初始化");
            LOGGER.warn("字段[" + key + "]验证码值未初始化，将为其自动初始化至ES");
            Date date = new Date();
            resumeEsHmacVO = new ResumeEsHmacVO();
            resumeEsHmacVO.setHmacId(key);
            resumeEsHmacVO.setHmac(hmac);
            resumeEsHmacVO.setCreateTime(date);
            resumeEsHmacVO.setUpdateTime(date);
            redisUtil.opsForValue().set(key,JSON.toJSONString(resumeEsHmacVO));
            return;
        }
        //若存在且为1条，则与实时验证码进行对比
        if (!hmac.equals(resumeEsHmacVO.getHmac())){
            //对比不正确，则抛出异常
            LOGGER.error("字段"+ key + "的数据可能被篡改");
            throw new online_education_Exception(201,"字段"+ key + "的数据可能被篡改");
        }
    }


    /**
     * @description: HMAC验证码批量签名（新增或修改）
     */
    public  void stateSecretSign(List<HmacVO> hmacVOList) throws Exception {
        Date date = new Date();
        List<ResumeEsHmacVO> updateList = new ArrayList<>();
        List<ResumeEsHmacVO> insertList = new ArrayList<>();
        for (HmacVO hmacVO : hmacVOList) {
            if (StringUtils.isBlank(hmacVO.getIdValue())){
                System.out.println("-1"+"传入的表字段主键值为空");
            }
            //判断es中是否存在该键值
            String key = hmacVO.getAgentCode()+"*"+hmacVO.getTableName()+"*"+hmacVO.getField().toLowerCase()+"*"+hmacVO.getIdValue();
            if (StringUtils.isEmpty(hmacVO.getFieldValue())){
                // linjiahao 20211215 修改当空值也进行加签
                checkStateSecretSign(key, signNullValue, date, updateList, insertList);
            }else {
                checkStateSecretSign(key, hmacVO.getFieldValue(), date, updateList, insertList);
            }
        }
    }

    private  void checkStateSecretSign(String key,String fieldValue, Date date, List<ResumeEsHmacVO> updateList, List<ResumeEsHmacVO> insertList)  {
        ResumeEsHmacVO resumeEsHmacVO =JSON.parseObject(redisUtil.opsForValue().get(key),ResumeEsHmacVO.class);
        if (resumeEsHmacVO!=null){
            //修改
            String hmac = fieldValue;
            resumeEsHmacVO.setHmac(hmac);
            resumeEsHmacVO.setUpdateTime(date);
            redisUtil.opsForValue().set(key,JSON.toJSONString(resumeEsHmacVO));
        }else {
            //新增
            String hmac = fieldValue;
            ResumeEsHmacVO resumeEsHmacVO1 = new ResumeEsHmacVO();
            resumeEsHmacVO1.setHmacId(key);
            resumeEsHmacVO1.setHmac(hmac);
            resumeEsHmacVO1.setCreateTime(date);
            resumeEsHmacVO1.setUpdateTime(date);
            redisUtil.opsForValue().set(key,JSON.toJSONString(resumeEsHmacVO1));
        }
    }



}
